# $NetBSD: cond-func.mk,v 1.19 2025/06/28 22:39:28 rillig Exp $
#
# Tests for those parts of the functions in .if conditions that are common
# among several functions.
#
# The below test uses the 'defined' function since it has no side-effects.
# The other functions would work equally well, except for 'empty', which
# parses its argument differently from the other functions.
#

DEF=			defined
${:UA B}=		variable name with spaces
${:UVAR(value)}=	variable name with parentheses
${:UVAR{value}}=	variable name with balanced braces

# Really strange variable names must be given indirectly via another variable,
# so that no unbalanced braces appear in the top-level expression.
VARNAME_UNBALANCED_BRACES=	VAR{{{value
${VARNAME_UNBALANCED_BRACES}=	variable name with unbalanced braces

.if !defined(DEF)
.  error
.endif

# Horizontal whitespace (space tab) after the opening parenthesis is ignored.
.if !defined( 	DEF)
.  error
.endif

# Horizontal whitespace (space tab) before the closing parenthesis is ignored.
.if !defined(DEF 	)
.  error
.endif

# The argument of a function must not directly contain whitespace.
# expect+1: Missing ")" after argument "A" for "defined"
.if !defined(A B)
.  error
.endif

# If necessary, the whitespace can be generated by an expression.
.if !defined(${:UA B})
.  error
.endif

# Characters that could be mistaken for operators must not appear directly
# in a function argument.  As with whitespace, these can be generated
# indirectly.
#
# It's not entirely clear why these characters are forbidden.
# The most plausible reason seems to be typo detection.
# expect+1: Missing ")" after argument "A" for "defined"
.if !defined(A&B)
.  error
.endif
# expect+1: Missing ")" after argument "A" for "defined"
.if !defined(A|B)
.  error
.endif

# Even parentheses may appear in variable names.
# They must be balanced though.
.if !defined(VAR(value))
.  error
.endif

# Braces do not have any special meaning when parsing arguments.
.if !defined(VAR{value})
.  error
.endif

# Braces do not have any special meaning when parsing arguments.
# They don't need to be balanced.
.if !defined(VAR{{{value)
.  error
.endif

# There may be spaces around the operators and parentheses, and even
# inside the parentheses.  The spaces inside the parentheses are not
# allowed for the 'empty' function (see cond-func-empty.mk), therefore
# they are typically omitted for the other functions as well.
.if ! defined ( DEF )
.  error
.endif

# Before cond.c 1.366 from 2024-07-06, the following condition was
# interpreted as defined(A) && defined(B). Each kind of .if directive has a
# default function that is called when a bare word is parsed.  For the plain
# .if directive, this function is 'defined'; see "struct If ifs" in cond.c.
# expect+1: Unknown operator "&"
.if A&B
.  error
.endif

# The empty variable is never defined.
.if defined()
.  error
.endif

# The plain word 'defined' is interpreted as 'defined(defined)', see
# CondParser_ComparisonOrLeaf.
# That variable is not defined (yet).
.if defined
.  error
.else
# expect+1: A plain function name is parsed as defined(...).
.  info A plain function name is parsed as defined(...).
.endif

# If a variable named 'defined' is actually defined, the bare word 'defined'
# is interpreted as 'defined(defined)', and the condition evaluates to true.
defined=	# defined but empty
.if defined
# expect+1: A plain function name is parsed as defined(...).
.  info A plain function name is parsed as defined(...).
.else
.  error
.endif

# A plain symbol name may start with one of the function names, in this case
# 'defined'.
.if defined-var
.  error
.else
# expect+1: Symbols may start with a function name.
.  info Symbols may start with a function name.
.endif

defined-var=	# defined but empty
.if defined-var
# expect+1: Symbols may start with a function name.
.  info Symbols may start with a function name.
.else
.  error
.endif

# expect+1: Missing ")" after argument "" for "defined"
.if defined(
.  error
.else
.  error
.endif

# expect+1: Missing ")" after argument "${:UVARNAME}.param" for "defined"
.if defined(${:UVARNAME}.param extra)
.  error
.else
.  error
.endif
